# -*- coding: utf-8 -*-
#
#    Copyright (C) 2012 Gonzalo Bonigo <gonzalobonigo@gmail.com>
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see http://www.gnu.org/licenses/
#


"""Este archivo contiene la implementacion del metodo lazy_diag_analyzer()."""


__all__ = [
    "lazy_diag_analyzer"
]


import os.path
import time
import sys
import os

from lts import utils
import lts


def lazy_diag_analyzer(parsed_args):
    system = parsed_args["system"]
    fault_set = parsed_args["fault_set"]
    sync_set = parsed_args["sync_set"]
    graphic = parsed_args["graphic"]
    heuristic_level = parsed_args["heuristic_level"]
    take_time = parsed_args["time"]
    verbose = parsed_args["verbose"]
    if verbose:
        print "\nINFORMATION"
        print "-----------"
    # Condicion para el ciclo pricipal.
    decide_result = False
    if verbose:
        iter = 1 # Cuenta las iteraciones para el modo verbose=True.
    # Para contar el tiempo global.
    if take_time:
        gt1 = time.time()
    while not decide_result:
        # Chequeo el tipo de sincronizacion.
        sync_type = utils.check_sync_type(system, sync_set)
        # Numero de iteracion.
        if verbose:
            print "\nIteration:", iter
        # Cantidad de subsistemas.
        if verbose:
            print "\nNumber of subsystems: ", len(system)
        # Tipo de sincronizacion en esta iteracion.
        if verbose:
            if sync_type == utils.SYNC_EMPTY:
                print "Synchronization type:  EMPTY"
            elif sync_type == utils.SYNC_PARTIAL:
                print "Synchronization type:  PARTIAL"
            else:
                print "Synchronization type:  FULL"
        if verbose:
            iter += 1
        # Dice si todos los subsistemas son diagnosticables.
        all_subsystems_diag = True
        # Almacena los resultados de los subsistemas no diagnosticables.
        all_nondiag_subsystems = []
        # Chequeo la diagnosticabilidad de los subsistemas.
        for subsystem in system:
            # - DBG -
            #lts.LTS.to_file(subsystem)
            #lts.LTS.to_file(subsystem.get_twinplant())
            # - DBG -
            subsystem.isdiag = None
            if verbose:
                print "\nChecking diagnosability for:", subsystem.name
            if take_time:
                t1 = time.time()
            if verbose:
                print "Building twin-plant..."
            subsystem.get_twinplant()
            if verbose:
                print "Analyzing..."
            diag_res = subsystem.is_diagnosable(fault_set,verbose)
            if take_time:
                t2 = time.time()
            if verbose:
                if diag_res['is_diag']:
                    print "It's diagnosable!"
                else:
                    print "It's non-diagnosable!"
                if take_time:
                    print "It takes",utils.str_time(t2-t1)
            subsystem.isdiag = diag_res['is_diag']
            all_subsystems_diag &= diag_res['is_diag']
            if not diag_res['is_diag']:
                all_nondiag_subsystems.append((subsystem,diag_res))
        # Chequeo si puedo decidir la diagnosticabilidad del sistema.
        if len(system) == 1: # Si hay un subsistema es facil.
            decide_result = True
            if all_subsystems_diag:
                print "\nRESULT"
                print "------"
                print "\nThe system is diagnosable."
            else:
                (subsystem,diag_res) = all_nondiag_subsystems[0]
                print "\nRESULT"
                print "------"
                print "\nThe system is non-diagnosable."
                utils.show_nondiag_info(subsystem, diag_res, graphic)
        elif (sync_type==utils.SYNC_EMPTY) and not all_subsystems_diag:
            # El sistema no es diagnosticable.
            decide_result = True
            print "\nRESULT"
            print "------"
            print "\nThe system is non-diagnosable because the " + \
                  "synchronization type"
            print "is EMPTY and there exist at least one non-diagnosable " + \
                  "subsystem."
            for (subsystem,diag_res) in all_nondiag_subsystems:
                utils.show_nondiag_info(subsystem, diag_res, graphic)
                print ''
        else:
            # No puedo decidir y hay mas de un sistema. Tengo que sincronizar.
            system = utils.synchronize(system,sync_set,heuristic_level,verbose)
    # Para contar el tiempo global.
    if take_time:
        gt2 = time.time()
    if take_time:
        print "\nTotal time:",utils.str_time(gt2-gt1),"\n"
